function cb(val) {
  console.log("视图更新啦")
}
// obj: 需要绑定的对象
// key: obj的某一个属性
// val: 具体的值
// 功能：实现对对象的响应式化
function defineReactive(obj, key, val) {
  const dep = new Dep();
  Object.defineProperty(obj, key, {
    enumerable: true, // 属性可枚举
    configurable: true, // 属性可被修改或删除
    get: function reactiveGetter() {
      // 将Dep.target(即当前的Watcher独享存入dep的subs中)
      dep.addSub(Dep.target)
      return val;
    },
    set: function reactiveSetter(newVal) {
      if (newVal === val) return;
      // cb(newVal);
      // 在set的时候触发dep的notify来通知所有的watcher对象更新视图
      dep.notify()
    }
  })
}
// value: 需要响应式的对象
// 功能： 通过遍历所有属性的方式对该对象的每一个属性都通过defineReactive处理
function observer(value) {
  if (!value || (typeof value !== 'object')) {
    return;
  }
  Object.keys(value).forEach((key) => {
    defineReactive(value, key, value[key]);
  })
}
// 订阅者Dep,主要作用是用来存放Watcher观察者对象的
class Dep {
  constructor() {
    // 用来存放Watcher对象的数组
    this.subs = [];
  }
  // 在subs中添加一个Watcher对象
  addSub(sub) {
    this.subs.push(sub)
  }
  // 通知所有Watcher对象更新视图
  notify() {
    this.subs.forEach((sub) => {
      sub.update();
    })
  }
}
// 观察者Watcher
class Watcher {
  constructor() {
    // 在new一个Watcher对象使将这个对象赋值给Dep.target
    Dep.target = this;
  }
  // 更新视图的方法
  update () {
    console.log('视图更新啦~')
  }
}
Dep.target = null;
// 封装Vue
class Vue {
  // Vue构造器
  constructor(options) {
    this._data = options.data;
    observer(this._data);

    // 这时候Dep.target会指向这个Watcher独享
    new Watcher()
  }
}

// 上面只要我们new一个Vue对象，就会将data中的数据进行响应式化。
let vm = new Vue({
  data: {
    test: 'I am zpp'
  }
})
vm._data.test = 'haha'
